﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NSDecisionTree.Classes;

namespace NSDecisionTree.Gui
{
    public partial class MainForm : Form
    {
        #region Needed Vars
        
        private DecisionTable currentLoaded;
        private DataTable currentLoadedAsDataTable;
        private bool loadingFile = false;
        private bool hasDependingChanges = false;
        private Graphic.DrawTree drawingTree = null;
        private XPicbox.XtendPicBox pictureBox1;
        private XPicbox.XtendPicBox pictureBox2;
        float[] valueArray = new float[] { 0.25f, 0.5f, 1, 1.5f, 2f, 2.5f, 3f, 4f, 5f};
        string bmpFileName = String.Empty;
        string bmpFileNameInteractive = String.Empty;
        string lastSelectedRootNode = String.Empty;
        int xPos = 0;
        int yPos = 0;
        
        #endregion

        #region ctor

        public MainForm()
        {
            InitializeComponent();
            init();
        }
        
        #endregion

        #region Methods
        
        public void loadFile(string Filename, string Delimiter, int ResultatField)
        {
            loadingFile = true;
            CSV_File testFile = new CSV_File(Filename,Delimiter,ResultatField);
            currentLoaded = testFile.CompleteDecisionObject;
            testFile.Dispose();
            updateUI();
            loadingFile = false;
        }

        private void updateUI()
        {
            if (currentLoaded != null)
                fillDataTable();

            if (currentLoadedAsDataTable != null)
            {
                Dgv_Table.DataSource = currentLoadedAsDataTable;
                foreach (DataGridViewColumn col in Dgv_Table.Columns)
                {
                    col.DefaultCellStyle.BackColor = Color.White;
                }
                Dgv_Table.Columns[Dgv_Table.Columns.Count - 1].DefaultCellStyle.BackColor = Color.LightGreen;
            }
            else
            {
                Dgv_Table.DataSource = null;
            }
            changesSaved();
        }

        private void fillDataTable()
        {
            DataTable dt = new DataTable();
            DataColumn autoincrement = new DataColumn("ID", typeof(System.Int32));
            autoincrement.AutoIncrement = true;
            autoincrement.AutoIncrementSeed = 1;
            autoincrement.ReadOnly = true;

            dt.Columns.Add(autoincrement);

            foreach (string element in currentLoaded.Captions)
                dt.Columns.Add(element);
            
            foreach(KeyValuePair<int, List<string>> element in currentLoaded.RowContent)
            {
                
                string[] tempArray = new string[element.Value.ToArray().Length + 1] ;
                // tempArray[0] = element.Key.ToString();
                int i = 1;
                foreach (string obj in element.Value.ToArray())
                {
                    tempArray[i] = obj;
                    i++;
                }
                // dt.Rows.Add(element.Key + element.Value.ToArray());
                dt.Rows.Add(tempArray);
                
                // dt.Rows.Add(element.Value.ToArray());
            }

            currentLoadedAsDataTable = dt;
        }

        private void changesMade()
        {
            hasDependingChanges = true;
            bt_Save.Enabled = true;
            bt_Reload.Enabled = true;
        }

        private void changesSaved()
        {
            hasDependingChanges = false;
            bt_Save.Enabled = false;
            bt_Reload.Enabled = false;
        }

        private DecisionTable getDecisionObjectFromDataGridView(out bool Error)
        {
            Error = false;
            List<string> captions = new List<string>();

            int indexOfID = 0;
            string[] temp = new string[Dgv_Table.Columns.Count];
            int[] index = new int[Dgv_Table.Columns.Count];
            for (int i = 0; i < Dgv_Table.Columns.Count; i++)
            {
                if (Dgv_Table.Columns[i].HeaderText.ToString() == "ID")
                    indexOfID = i;

                index[Dgv_Table.Columns[i].DisplayIndex] = Dgv_Table.Columns[i].Index;
                temp[Dgv_Table.Columns[i].DisplayIndex] = Dgv_Table.Columns[i].HeaderText.ToString();
            }

            foreach (string element in temp)
                captions.Add(element);

            captions.Remove("ID");

            DecisionTable ds = new DecisionTable(captions);

            foreach (DataGridViewRow row in Dgv_Table.Rows)
            {
                if (row.Cells["ID"].Value == null)
                    break;

                List<string> rowElement = new List<string>();

                for (int i = 0; i < row.Cells.Count; i++)
                {
                    DataGridViewCell cell = row.Cells[index[i]];
                    if (cell.OwningColumn.HeaderText.ToString() != "ID")
                    {
                        rowElement.Add(cell.Value.ToString().Trim());
                        if (cell.Value.ToString().Trim() == String.Empty)
                            Error = true;
                    }
                }

                ds.AddRowItem(rowElement);
            }

            return ds;
        }

        private void saveToExcel()
        {
            if (DialogResult.OK == sfd_SaveFileExcel.ShowDialog())
            {
                DataTable tempTable = currentLoadedAsDataTable.Copy();
                tempTable.Columns.Remove("ID");
                /*
                DataSet ds = new DataSet();
                ds.Tables.Add(tempTable);
                Tools.Tools.exportToExcel(ds,sfd_SaveFileExcel.FileName);
                */
                // Tools.CreateExcelFile.CreateExcelDocument(tempTable,sfd_SaveFileExcel.FileName);
                Tools.ExcelFileHandling.SaveToExcel(tempTable, sfd_SaveFileExcel.FileName);
            }
        }

        private void makeVisible()
        {
            tsmi_ExportExcel.Enabled = true;
            tsmi_Speichern.Enabled = true;
            tsmi_Schließen.Enabled = true;
            contextMenuStrip1.Enabled = true;
        }

        private void makeInvisible()
        {
            tsmi_ExportExcel.Enabled = false;
            tsmi_Speichern.Enabled = false;
            tsmi_Schließen.Enabled = false;
            contextMenuStrip1.Enabled = false;
        }

        private void init()
        {
            label1.Text = valueArray[trackBar1.Value].ToString();
            label2.Text = valueArray[trackBar2.Value].ToString();
            pictureBox1 = new XPicbox.XtendPicBox();
            pictureBox1.Dock = DockStyle.Fill;
            pictureBox2 = new XPicbox.XtendPicBox();
            pictureBox2.Dock = DockStyle.Fill;
            panel2.Controls.Add(pictureBox1);
            panel3.Controls.Add(pictureBox2);
            pictureBox1.ContextMenuStrip = contextMenuStrip1;
            pictureBox2.ContextMenuStrip = contextMenuStrip2;
            lastSelectedRootNode = String.Empty;
            makeInvisible();
        }

        private Image getImageResized(int imageIndex)
        {
            int trackBarValue = 0;

            if (imageIndex == 1)
                trackBarValue = trackBar1.Value;
            else if (imageIndex == 2)
                trackBarValue = trackBar2.Value;

            if (drawingTree != null)
            {
                Size oldSize = drawingTree.BmpTree.Size;
                float value = valueArray[trackBarValue];
                Size newSize = new Size((int)(oldSize.Width * value), (int)(oldSize.Height * value));
                return Tools.Tools.resizeImage(drawingTree.BmpTree, newSize);
            }
            else
            {
                return new Bitmap(2, 2);
            }
        }

        #endregion

        #region Menues and Events

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (DialogResult.OK != MessageBox.Show("Wirklich beenden?", "Exit?", MessageBoxButtons.OKCancel))
                e.Cancel = true;
        }

        private void tsmi_Einlesen_Click(object sender, EventArgs e)
        {
            string delimiter;
            string filename;
            int resultatField;

            if (DialogResult.OK == ofd_LoadFile.ShowDialog())
            {
                tsmi_Schließen_Click(sender, e);
                filename = ofd_LoadFile.FileName;
                OpenFileDialogExtender ofdE = new OpenFileDialogExtender();
                if (DialogResult.OK == ofdE.ShowDialog())
                {
                    delimiter = ofdE.Delimiter;
                    resultatField = ofdE.ResultatField;
                    loadFile(filename, delimiter, resultatField);
                    makeVisible();
                }
            }
        }

        private void tsmi_Beenden_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void tsmi_Speichern_Click(object sender, EventArgs e)
        {
            bool ok = true;
            if (hasDependingChanges)
            {
                if (DialogResult.Cancel == MessageBox.Show("Achtung: gemachte Änderungen müssen erst mit SaveTable gespeichert werden!!!", "Achtung", MessageBoxButtons.OKCancel))
                    ok = false;
            }
            if (!ok)
                return;

            SaveFileDialogExtender sfdE = new SaveFileDialogExtender();
            if (DialogResult.OK == sfdE.ShowDialog())
            {
                if (DialogResult.OK == sfd_SaveFile.ShowDialog())
                {
                    string filename = sfd_SaveFile.FileName;
                    string[] content = currentLoaded.GetAsCsvStringArray(sfdE.Delimiter);

                    File.WriteAllLines(filename, content);
                }
            }
        }

        private void tsmi_ExportExcel_Click(object sender, EventArgs e)
        {
            bool ok = true;
            if (hasDependingChanges)
            {
                if (DialogResult.Cancel == MessageBox.Show("Achtung: gemachte Änderungen müssen erst mit SaveTable gespeichert werden!!!", "Achtung", MessageBoxButtons.OKCancel))
                    ok = false;
            }
            if (ok)
                saveToExcel();
        }

        private void tsmi_ImportExcel_Click(object sender, EventArgs e)
        {
            DataTable da = new DataTable();
            if (DialogResult.OK == ofd_LoadExcelFile.ShowDialog())
            {
                tsmi_Schließen_Click(sender, e);
                List<string> captions = new List<string>();
                List<List<string>> elements = new List<List<string>>();
                loadingFile = true;
                try
                {
                    Tools.ExcelFileHandling.LoadFromExcel(ofd_LoadExcelFile.FileName, out captions, out elements);

                    if (captions != null && elements != null)
                    {
                        DecisionTable ds = new DecisionTable(captions);
                        foreach (List<string> ele in elements)
                        {
                            ds.AddRowItem(ele);
                        }
                        currentLoaded = ds;
                        updateUI();
                        makeVisible();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                loadingFile = false;
            }
        }

        private void tsmi_Schließen_Click(object sender, EventArgs e)
        {
            currentLoaded = null;
            currentLoadedAsDataTable = null;
            loadingFile = false;
            hasDependingChanges = false;
            updateUI();
            changesSaved();
            makeInvisible();

            bmpFileName = Path.GetTempFileName();
            bmpFileNameInteractive = Path.GetTempFileName();
            Bitmap bmp = new Bitmap(2, 2);
            bmp.Save(bmpFileName);
            bmp.Save(bmpFileNameInteractive);

            pictureBox1.PictureFile = bmpFileName;
            pictureBox2.PictureFile = bmpFileNameInteractive;
            tc_DC_Pages.SelectedIndex = 0;
            trackBar1.Value = 2;
            trackBar2.Value = 2;
        }

        private void bt_Save_Click(object sender, EventArgs e)
        {
            List<string> captions = new List<string>();
            bool error = false;

            DecisionTable ds = getDecisionObjectFromDataGridView(out error);

            /*
            foreach (DataGridViewColumn element in Dgv_Table.Columns)
            {
                if (element.HeaderCell.Value.ToString() != "ID")
                    captions.Add(element.HeaderCell.Value.ToString());
            }

            // captions.RemoveAt(0);
            DecisionObject ds = new DecisionObject(captions);

            foreach (DataGridViewRow rowElement in Dgv_Table.Rows)
            {
                if (rowElement.Cells["ID"].Value == null)
                    break;

                List<string> objects = new List<string>();
                foreach (DataGridViewCell dgvc in rowElement.Cells)
                {
                    if (dgvc.OwningColumn.Name != "ID")
                    {
                        objects.Add(dgvc.Value.ToString().Trim());
                        if (dgvc.Value.ToString().Trim() == String.Empty)
                            error = true;
                    }
                }
                // objects.RemoveAt(0);
                ds.AddRowItem(objects);
            }
            */
            /*
            foreach (DataRow rowElement in currentLoadedAsDataTable.Rows)
            {
                List<string> objects = new List<string>();
                object[] objectArray = rowElement.ItemArray;
                foreach (object itemElement in objectArray)
                {
                    objects.Add(itemElement.ToString());
                    if (itemElement.ToString().Trim() == String.Empty)
                        error = true;
                }
                objects.RemoveAt(0);
                ds.AddRowItem(objects);
            }
            */

            if (!error)
            {
                currentLoaded = ds;
                updateUI();
                // currentLoadedAsDataTable = (DataTable)Dgv_Table.DataSource;
                // changesSaved();
            }
            else
            {
                if (DialogResult.OK == MessageBox.Show("Es ist ein Fehler aufgetreten. [Empty Fields].\r\n" +
                                "Wirklich Speichern?", "Error", MessageBoxButtons.OKCancel))
                {
                    currentLoaded = ds;
                    updateUI();
                    // currentLoadedAsDataTable = (DataTable)Dgv_Table.DataSource;
                    // changesSaved();
                }
            }
        }

        private void bt_Reload_Click(object sender, EventArgs e)
        {
            updateUI();
            changesSaved();
        }

        private void Dgv_Table_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            if (!loadingFile && !hasDependingChanges)
            {
                changesMade();
            }
        }

        private void Dgv_Table_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (!loadingFile && !hasDependingChanges)
            {
                changesMade();
            }
        }

        private void Dgv_Table_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
        {
            if (!loadingFile && !hasDependingChanges)
            {
                changesMade();
            }

        }

        private void tsmi_CreateNewTable_Click(object sender, EventArgs e)
        {
            CreateNewTable cnt = new CreateNewTable();
            if (DialogResult.OK == cnt.ShowDialog())
            {
                List<string> captions = cnt.ListBoxItems;
                DecisionTable ds = new DecisionTable(captions);
                currentLoaded = ds;
                updateUI();
                makeVisible();
            }
        }

        private void tc_DC_Pages_SelectedIndexChanged(object sender, EventArgs e)
        {
            bt_Select.Enabled = false;
            if (tc_DC_Pages.SelectedIndex == 1 && currentLoadedAsDataTable != null)
            {
                DataTable forTree = currentLoadedAsDataTable.Copy();
                forTree.Columns.Remove("ID");
                drawingTree = new Graphic.DrawTree(forTree);
                if (drawingTree.BmpTree != null)
                {
                    bmpFileName = Path.GetTempFileName();
                    Image img = getImageResized(1);
                    Tools.Tools.saveBMP(img, bmpFileName);
                    pictureBox1.PictureFile = bmpFileName;
                    pictureBox1.Update();
                }
            }
            else if (tc_DC_Pages.SelectedIndex == 2 && currentLoadedAsDataTable != null)
            {
                bt_Select.Enabled = true; 
                //TODO: implement here the interactive decision tree
                DataTable forTree = currentLoadedAsDataTable.Copy();
                forTree.Columns.Remove("ID");

                if ( lastSelectedRootNode == String.Empty)
                    lastSelectedRootNode = "_**#'";

                /*
                    * No automatism. Button implemented to select manually.
                    * 
                SelectRootElement sre = new SelectRootElement(forTree.Copy());
                if (sre.ShowDialog() == DialogResult.OK)
                    rootElement = sre.RootElement;
                */

                drawingTree = new Graphic.DrawTree(forTree, lastSelectedRootNode);
                if (drawingTree.BmpTree != null)
                {
                    bmpFileNameInteractive = Path.GetTempFileName();
                    Image img = getImageResized(2);
                    Tools.Tools.saveBMP(img, bmpFileNameInteractive);
                    pictureBox2.PictureFile = bmpFileNameInteractive;
                    pictureBox2.Update();
                }
            }
            else
            {
                pictureBox1.PictureFile = bmpFileName;
                pictureBox2.PictureFile = bmpFileName;
            }
        }

        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            if (drawingTree != null)
            {
                /*
                Size oldSize = drawingTree.BmpTree.Size;
                float value = valueArray[trackBar1.Value];
                Size newSize = new Size((int)(oldSize.Width * value),(int)(oldSize.Height * value));
                */

                pictureBox1.PictureFile = String.Empty;
                pictureBox1.Update();

                bmpFileName = Path.GetTempFileName();
                Tools.Tools.saveBMP(getImageResized(1), bmpFileName);

                pictureBox1.PictureFile = bmpFileName;
                pictureBox1.Update();
            }
            label1.Text = valueArray[trackBar1.Value].ToString();

        }

        private void saveAsBmpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK == sfd_SaveBitmap.ShowDialog())
            {
                int test = 0;

                if (sender.Equals((object)saveAsBmpToolStripMenuItem))
                    test = 1;
                else if (sender.Equals((object)saveAsBmpToolStripMenuItem_2))
                    test = 2;

                // if (sender.ToString)
                Image image = getImageResized(test);
                image.Save(sfd_SaveBitmap.FileName);
            }

        }

        private void getTableToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int trackbarValue = 0;
            if (sender.Equals((object)getTableToolStripMenuItem))
                trackbarValue = trackBar1.Value;
            else if (sender.Equals((object)getTableToolStripMenuItem_2))
                trackbarValue = trackBar2.Value;

            Graphic.Node node = drawingTree.getNodes(xPos, yPos, valueArray[trackbarValue]);
            ShowNodeRepresentation snr = new ShowNodeRepresentation();
            snr.NodeToRepresent = node;
            snr.Show();
        }

        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            Point p = pictureBox1.PointToClient(new Point(Cursor.Position.X, Cursor.Position.Y));
            xPos = p.X;
            yPos = p.Y;
        }

        #endregion

        private void changeItemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Graphic.Node node = drawingTree.getNodes(xPos, yPos, valueArray[trackBar2.Value]);
            MessageBox.Show("Derzeit noch nicht implementiert.");
            // ShowNodeRepresentation snr = new ShowNodeRepresentation();
            // snr.NodeToRepresent = node;
            // snr.Show();
        }

        private void contextMenuStrip2_Opening(object sender, CancelEventArgs e)
        {
            Point p = pictureBox2.PointToClient(new Point(Cursor.Position.X, Cursor.Position.Y));
            xPos = p.X;
            yPos = p.Y;
        }

        private void trackBar2_ValueChanged(object sender, EventArgs e)
        {
            if (drawingTree != null)
            {
                /*
                Size oldSize = drawingTree.BmpTree.Size;
                float value = valueArray[trackBar1.Value];
                Size newSize = new Size((int)(oldSize.Width * value),(int)(oldSize.Height * value));
                */

                pictureBox2.PictureFile = String.Empty;
                pictureBox2.Update();

                bmpFileNameInteractive = Path.GetTempFileName();
                Tools.Tools.saveBMP(getImageResized(2), bmpFileNameInteractive);

                pictureBox2.PictureFile = bmpFileNameInteractive;
                pictureBox2.Update();
            }
            label2.Text = valueArray[trackBar2.Value].ToString();

        }

        private void bt_Select_Click(object sender, EventArgs e)
        {
            DataTable forTree = currentLoadedAsDataTable.Copy();
            forTree.Columns.Remove("ID");

            SelectRootElement sre = new SelectRootElement(forTree.Copy());
            if (sre.ShowDialog() == DialogResult.OK)
                lastSelectedRootNode = sre.RootElement;

            drawingTree = new Graphic.DrawTree(forTree, lastSelectedRootNode);
            if (drawingTree.BmpTree != null)
            {
                bmpFileNameInteractive = Path.GetTempFileName();
                Image img = getImageResized(2);
                Tools.Tools.saveBMP(img, bmpFileNameInteractive);
                pictureBox2.PictureFile = bmpFileNameInteractive;
                pictureBox2.Update();
            }
        }

        private void tsmi_About_Click(object sender, EventArgs e)
        {
            About about = new About();
            about.Show();
        }

        private void optionenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Options o = new Options();
            if (DialogResult.OK == o.ShowDialog())
            {
                Tools.Tools.OPTION_SHOW_ALL = o.Option_Show_All;
            }
        }

    }
}
